﻿package _A_TJTable;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.EventObject;

import javax.swing.AbstractCellEditor;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
 * 2011-6-3 23:34:54
 * @author Administrator
 * 演示了在JTable中添加JCheckBox和JTextArea
 */
public class JTable_CellRender2 {
    JFrame frame;
    Container contentPane;
    JScrollPane jsp;
    JTable table;
    public JTable_CellRender2(){
        frame=new JFrame("表格组件测试");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        contentPane=frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        String name[]={"姓名","语文","数学","合格","座右铭"};
        Object data[][]={
            {"王鹏",91,100,true,"哈哈哈哈,我好高兴啊"},
            {"李兵",99,89,false,"你高兴个屁啊"},
            {"肖龙",100,100,true,"我就是高兴"}
        };
        DefaultTableModel dtm=new DefaultTableModel(data,name);
        dtm.setColumnCount(10);
        dtm.setRowCount(10);
        table=new JTable(dtm);
        //设置表格属性
        table.setRowHeight(50);
//        table.setRowHeight(4, 4*table.getRowHeight());
        table.setCellSelectionEnabled(true);
        table.setPreferredScrollableViewportSize(new Dimension(400,100));
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        //设置列属性
        TableColumnModel tcm=table.getColumnModel();
        tcm.setColumnMargin(10);
        tcm.getColumn(3).setCellEditor(new DefaultCellEditor(new JCheckBox("合格",true)));
        JTextArea area=new JTextArea(10,10);
        area.setLineWrap(true);
        tcm.getColumn(4).setCellEditor(new MyDefaultCellEditor(area));
        DefaultTableCellRenderer dtcr=new DefaultTableCellRenderer(){
            /**
             * 
             */
            private static final long serialVersionUID = 1L;

            public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
                if(column==4){
                    Object object=table.getModel().getValueAt(row, column);
                    JTextArea tmpArea=(JTextArea)table.getColumnModel().getColumn(column).getCellEditor()
                                        .getTableCellEditorComponent(table, value, isSelected, row, column);
                    JTextArea jta=new JTextArea(object==null?"":object.toString(),tmpArea.getRows(),tmpArea.getColumns());
                    jta.setLineWrap(true);
                    Color fg = null;
                    Color bg = null;

                    JTable.DropLocation dropLocation = table.getDropLocation();
                    if (dropLocation != null
                            && !dropLocation.isInsertRow()
                            && !dropLocation.isInsertColumn()
                            && dropLocation.getRow() == row
                            && dropLocation.getColumn() == column) {

                        fg = UIManager.getColor("Table.dropCellForeground");
                        bg = UIManager.getColor("Table.dropCellBackground");

                        isSelected = true;
                    }

                    if (isSelected) {
                        jta.setForeground(fg == null ? table.getSelectionForeground()
                                                       : fg);
                        jta.setBackground(bg == null ? table.getSelectionBackground()
                                                       : bg);
                    } else {
                        jta.setForeground(table.getForeground());
                        jta.setBackground( table.getBackground());
                    }

                    jta.setFont(table.getFont());

                    if (hasFocus) {
                        Border border = null;
                        if (isSelected) {
                            border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
                        }
                        if (border == null) {
                            border = UIManager.getBorder("Table.focusCellHighlightBorder");
                        }
                        jta.setBorder(border);

                        if (!isSelected && table.isCellEditable(row, column)) {
                            Color col;
                            col = UIManager.getColor("Table.focusCellForeground");
                            if (col != null) {
                                jta.setForeground(col);
                            }
                            col = UIManager.getColor("Table.focusCellBackground");
                            if (col != null) {
                                jta.setBackground(col);
                            }
                        }
                    } else {
                        jta.setBorder(noFocusBorder);
                    }
                    return jta;
                }
                else if(column==3){
                    Object object=table.getModel().getValueAt(row, column);
                    JCheckBox jcb=new JCheckBox("合格",object==null?false:(Boolean)object);
                    jcb.setBackground(Color.white);
                    return jcb;
//                    return table.getColumnModel().getColumn(column).getCellEditor().getTableCellEditorComponent(table, value, isSelected, row, column);
                }
                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
        };        
        for(int i=0;i<tcm.getColumnCount();i++){
            TableColumn tc=tcm.getColumn(i);
            tc.setPreferredWidth(100);
            tc.setCellRenderer(dtcr);
//            tc.setMinWidth(50);
        }
        //监听代码
        dtm.addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                System.out.println("第一行:"+e.getFirstRow()+",最后一行:"+e.getLastRow()+",列:"+e.getColumn());
                System.out.println(table.getValueAt(e.getFirstRow(), e.getColumn()));
            }
        });
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                int rows[]=table.getSelectedRows();
                int columns[]=table.getSelectedColumns();
                System.out.println("rows:"+Arrays.toString(rows));
                System.out.println("columns:"+Arrays.toString(columns));
            }
        });
        jsp=new JScrollPane(table);
        contentPane.add(jsp,BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    public static void main(String args[]){
        new JTable_CellRender2();
    }
}
class MyDefaultCellEditor extends AbstractCellEditor
    implements TableCellEditor {

//
//  Instance Variables
//

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    /** The Swing component being edited. */
    protected JComponent editorComponent;
    /**
     * The delegate class which handles all methods sent from the
     * <code>CellEditor</code>.
     */
    protected EditorDelegate delegate;
    /**
     * An integer specifying the number of clicks needed to start editing.
     * Even if <code>clickCountToStart</code> is defined as zero, it
     * will not initiate until a click occurs.
     */
    protected int clickCountToStart = 1;

//
//  Constructors
//

    /**
     * Constructs a <code>DefaultCellEditor</code> that uses a text field.
     *
     * @param textField  a <code>JTextField</code> object
     */
    public MyDefaultCellEditor(final JTextArea area) {
        editorComponent = area;
	this.clickCountToStart = 2;
        delegate = new EditorDelegate() {
            public void setValue(Object value) {
                System.out.println("value:"+(value!=null?value.toString():"null"));
		area.setText((value != null) ? value.toString() : "");
            }
//
	    public Object getCellEditorValue() {
		return area.getText();
	    }
        };

    }


    /**
     * Returns a reference to the editor component.
     *
     * @return the editor <code>Component</code>
     */
    public Component getComponent() {
	return editorComponent;
    }

//
//  Modifying
//

    /**
     * Specifies the number of clicks needed to start editing.
     *
     * @param count  an int specifying the number of clicks needed to start editing
     * @see #getClickCountToStart
     */
    public void setClickCountToStart(int count) {
	clickCountToStart = count;
    }

    /**
     * Returns the number of clicks needed to start editing.
     * @return the number of clicks needed to start editing
     */
    public int getClickCountToStart() {
	return clickCountToStart;
    }

//
//  Override the implementations of the superclass, forwarding all methods
//  from the CellEditor interface to our delegate.
//

    /**
     * Forwards the message from the <code>CellEditor</code> to
     * the <code>delegate</code>.
     * @see EditorDelegate#getCellEditorValue
     */
    public Object getCellEditorValue() {
        return delegate.getCellEditorValue();
    }

    /**
     * Forwards the message from the <code>CellEditor</code> to
     * the <code>delegate</code>.
     * @see EditorDelegate#isCellEditable(EventObject)
     */
    public boolean isCellEditable(EventObject anEvent) {
	return delegate.isCellEditable(anEvent);
    }

    /**
     * Forwards the message from the <code>CellEditor</code> to
     * the <code>delegate</code>.
     * @see EditorDelegate#shouldSelectCell(EventObject)
     */
    public boolean shouldSelectCell(EventObject anEvent) {
	return delegate.shouldSelectCell(anEvent);
    }

    /**
     * Forwards the message from the <code>CellEditor</code> to
     * the <code>delegate</code>.
     * @see EditorDelegate#stopCellEditing
     */
    public boolean stopCellEditing() {
	return delegate.stopCellEditing();
    }

    /**
     * Forwards the message from the <code>CellEditor</code> to
     * the <code>delegate</code>.
     * @see EditorDelegate#cancelCellEditing
     */
    public void cancelCellEditing() {
	delegate.cancelCellEditing();
    }
//
//  Implementing the CellEditor Interface
//
    /** Implements the <code>TableCellEditor</code> interface. */
    public Component getTableCellEditorComponent(JTable table, Object value,
						 boolean isSelected,
						 int row, int column) {
        delegate.setValue(value);
        if (editorComponent instanceof JTextArea) {
            //in order to avoid a "flashing" effect when clicking a checkbox
            //in a table, it is important for the editor to have as a border
            //the same border that the renderer has, and have as the background
            //the same color as the renderer has. This is primarily only
            //needed for JCheckBox since this editor doesn't fill all the
            //visual space of the table cell, unlike a text field.
//            TableCellRenderer renderer = table.getCellRenderer(row, column);
//            Component c = renderer.getTableCellRendererComponent(table, value,
//                    isSelected, true, row, column);
//            if (c != null) {
//                editorComponent.setOpaque(true);
//                editorComponent.setBackground(c.getBackground());
//                if (c instanceof JComponent) {
//                    editorComponent.setBorder(((JComponent)c).getBorder());
//                }
//            } else {
//                editorComponent.setOpaque(false);
//            }
        }
	return editorComponent;
    }


//
//  Protected EditorDelegate class
//

    /**
     * The protected <code>EditorDelegate</code> class.
     */
    protected class EditorDelegate  {

        /**  The value of this cell. */
        protected Object value;

       /**
        * Returns the value of this cell.
        * @return the value of this cell
        */
        public Object getCellEditorValue() {
            return value;
        }

       /**
        * Sets the value of this cell.
        * @param value the new value of this cell
        */
    	public void setValue(Object value) {
	    this.value = value;
	}

       /**
        * Returns true if <code>anEvent</code> is <b>not</b> a
        * <code>MouseEvent</code>.  Otherwise, it returns true
        * if the necessary number of clicks have occurred, and
        * returns false otherwise.
        *
        * @param   anEvent         the event
        * @return  true  if cell is ready for editing, false otherwise
        * @see #setClickCountToStart
        * @see #shouldSelectCell
        */
        public boolean isCellEditable(EventObject anEvent) {
	    if (anEvent instanceof MouseEvent) {
		return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
	    }
	    return true;
	}

       /**
        * Returns true to indicate that the editing cell may
        * be selected.
        *
        * @param   anEvent         the event
        * @return  true
        * @see #isCellEditable
        */
        public boolean shouldSelectCell(EventObject anEvent) {
            return true;
        }

       /**
        * Returns true to indicate that editing has begun.
        *
        * @param anEvent          the event
        */
        public boolean startCellEditing(EventObject anEvent) {
	    return true;
	}

       /**
        * Stops editing and
        * returns true to indicate that editing has stopped.
        * This method calls <code>fireEditingStopped</code>.
        *
        * @return  true
        */
        public boolean stopCellEditing() {
	    fireEditingStopped();
	    return true;
	}

       /**
        * Cancels editing.  This method calls <code>fireEditingCanceled</code>.
        */
       public void cancelCellEditing() {
	   fireEditingCanceled();
       }

    }

} // End of class JCellEditor
